﻿using System;
using System.Collections;
using System.Data;

using zijian666.Converts.Abstractions;
using zijian666.Converts.Convertor.Base;
using zijian666.Converts.Core;
using zijian666.Converts.Extensions;

namespace zijian666.Converts.Convertor;

/// <summary>
/// <seealso cref="DataTable"/> 转换器
/// </summary>
public class DataTableConvertor : AllowNullConvertor<DataTable>
                                , IFrom<DataView, DataTable>
                                , IFrom<IDataReader, DataTable>
                                , IFrom<IEnumerator, DataTable>
{
    /// <inheritdoc />
    public ConvertResult<DataTable> From(IConvertContext context, DataView input!!) => input.ToTable();

    /// <inheritdoc />
    public ConvertResult<DataTable> From(IConvertContext context, IDataReader input!!)
    {
        var table = new DataTable();
        table.Load(input);
        return table;
    }

    /// <inheritdoc />
    public ConvertResult<DataTable> From(IConvertContext context, IEnumerator input!!)
    {
        var table = new DataTable();
        while (input.MoveNext())
        {
            var enumerator = new KeyValueEnumerator<string, object>(context, input.Current);
            if (!enumerator.KeyIsString)
            {
                return context.ConvertFail(this, input);
            }

            var row = table.NewRow();
            while (enumerator.MoveNext())
            {
                var key = enumerator.GetKey();
                if (!key.Success)
                {
                    var rs = context.Settings.GetResourceStrings();
                    var message = string.Format(rs.COLLECTION_KEY_FAIL, TypeFriendlyName, enumerator.OriginalKey);
                    return new InvalidCastException(message, key.Exception);
                }

                var value = enumerator.GetValue();
                if (!value.Success)
                {
                    var rs = context.Settings.GetResourceStrings();
                    var message = string.Format(rs.COLLECTION_ADD_FAIL, TypeFriendlyName, key.Value, enumerator.OriginalValue);
                    return new InvalidCastException(message, key.Exception);
                }

                var column = table.Columns[key.Value] ?? table.Columns.Add(key.Value);
                row[column] = value.Value;
            }

            table.Rows.Add(row);
        }

        return table;
    }
}
